#include "gfx_tilemap.h"


//-----------------------------------------------------------------------------
// Tilemap
//-----------------------------------------------------------------------------


GFX_Tilemap* gfx_tilemap_create(const char *image, int width, int height)
{
    GFX_Tilemap *tilemap=mem_allocate(sizeof(GFX_Tilemap));

    //gfx_image_get(image);

    tilemap->x=0;//X position of the tilemap
    tilemap->y=0;//Y position of the tilemap

    tilemap->width=width;
    tilemap->height=height;
    tilemap->image= gfx_image_get(image);

    tilemap->numberOfTiles=width*height;
    tilemap->tiles=mem_allocate(sizeof(int)*width*height);

    //gfx_tilemap_set_tiles(tilemap,0,0,width,height,0);
    return tilemap;
}

void gfx_tilemap_delete(GFX_Tilemap *tilemap)
{
    if(tilemap == 0) return;
    mem_free(tilemap->tiles);
    mem_free(tilemap);
}

void gfx_tilemap_set_tile(GFX_Tilemap *t, int x, int y, int tile)
{
    if(x < 0 || x >= t->width || y < 0 || y >= t->height) return;
    t->tiles[x+(y*t->width)]=tile;
}

void gfx_tilemap_set_tiles(GFX_Tilemap *t, int x, int y, int w, int h, int tile)
{
    int i,j;
    for(i=0;i<w;i++)
    {
        for(j=0;j<h;j++)
        {
            gfx_tilemap_set_tile(t,x+i,y+j,tile);
        }
    }
}

int gfx_tilemap_get_tile(GFX_Tilemap *t, int x, int y)
{
    if(x < 0 || x >= t->width || y < 0 || y >= t->height) return 0;
    return t->tiles[x+(y*t->width)];
}


void gfx_render_tilemap(GFX_Tilemap *tilemap)
{
    if(tilemap == 0) { return; }
    if(tilemap->image == 0)
    {
        log_puts(LOG_WARN, "Tried to render a GFX_Tilemap without an image");
        return;
    }
    GFX_Sprite sprite;
    sprite.image = tilemap->image;

    sprite.y = tilemap->y;

    for(int y = 0; y < tilemap->height; y++)
    {
        sprite.x = tilemap->x;

        for(int x = 0; x < tilemap->width; x++)
        {
            sprite.frame = tilemap->tiles[x+y*tilemap->width];
            gfx_render_sprite(&sprite);
            sprite.x += tilemap->image->width / tilemap->image->columns;
        }

        sprite.y += tilemap->image->height / tilemap->image->rows;
    }
}

void gfx_tilemap_generate(GFX_Tilemap *t)
{
    int ran, ran2, y_door1, y_door2, done=0;
    int x_on, y_on;

    //Setting of the map default tiles
    gfx_tilemap_set_tiles(t,0,0,(t->width/2),(t->height),3);
    for(int i=0;i<t->width/2;i++)
    {
        gfx_tilemap_set_tile(t,i,0,2);
        gfx_tilemap_set_tile(t,i,t->height-1,2);
    }
    for(int i=0;i<t->height;i++)
    {
        gfx_tilemap_set_tile(t,0,i,1);
        gfx_tilemap_set_tile(t,t->width/2-1,i,1);
    }
    gfx_tilemap_set_tile(t,0,0,3);
    gfx_tilemap_set_tile(t,0,t->width/2-1,3);
    gfx_tilemap_set_tile(t,t->height-1,0,3);
    gfx_tilemap_set_tile(t,t->height-1,t->width/2-1,3);
    ran=y_door1=(rand()%(t->height-2))+1;
    gfx_tilemap_set_tile(t,0,ran,4);
    ran=y_door2=(rand()%(t->height-2))+1;
    gfx_tilemap_set_tile(t,t->width/2-1,ran,5);

    //Creation of the map itself
    gfx_tilemap_set_tile(t,1,y_door1,0);
    x_on=1;
    y_on=y_door1;
    do
    {
        if(gfx_tilemap_get_tile(t,t->width/2-1,y_door2)==0) {done=1;}
        ran=rand()%4;
        ran2=(rand()%3)+1;
        switch (ran)
        {
            case 0:
            if(gfx_tilemap_get_tile(t,x_on-1,y_on)==3 || gfx_tilemap_get_tile(t,x_on-1,y_on)==0)
            {
                for(int i=ran2;i>=0;i--)
                {
                    gfx_tilemap_set_tile(t,x_on-ran2,y_on,0);
                }
                x_on-=ran2;
            }
            else
            {
                for(int i=ran2;i>=0;i--)
                {
                    gfx_tilemap_set_tile(t,x_on+ran2,y_on,0);
                }
                x_on+=ran2;
            }
            break;
            case 1:
            if(gfx_tilemap_get_tile(t,x_on,y_on-1)==3 || gfx_tilemap_get_tile(t,x_on,y_on-1)==0)
            {
                for(int i=ran2;i>=0;i--)
                {
                    gfx_tilemap_set_tile(t,x_on,y_on-ran2,0);
                }
                y_on-=ran2;
            }
            else
            {
                for(int i=ran2;i>=0;i--)
                {
                    gfx_tilemap_set_tile(t,x_on,y_on+ran2,0);
                }
                y_on+=ran2;
            }
            break;
            case 2:
            if(gfx_tilemap_get_tile(t,x_on+1,y_on)==3 || gfx_tilemap_get_tile(t,x_on+1,y_on)==0)
            {
                for(int i=ran2;i>=0;i--)
                {
                    gfx_tilemap_set_tile(t,x_on+ran2,y_on,0);
                }
                x_on+=ran2;
            }
            else
            {
                for(int i=ran2;i>=0;i--)
                {
                    gfx_tilemap_set_tile(t,x_on-ran2,y_on,0);
                }
                x_on-=ran2;
            }
            break;
            case 3:
            if(gfx_tilemap_get_tile(t,x_on,y_on+1)==3 || gfx_tilemap_get_tile(t,x_on,y_on+1)==0)
            {
                for(int i=ran2;i>=0;i--)
                {
                    gfx_tilemap_set_tile(t,x_on,y_on+ran2,0);
                }
                y_on+=ran2;
            }
            else
            {
                for(int i=ran2;i>=0;i--)
                {
                    gfx_tilemap_set_tile(t,x_on,y_on-ran2,0);
                }
                y_on-=ran2;
            }
            break;
        }
        for(int i= 0;i<t->width;i++)
        {
            for(int j = 0;j<t->height;j++)
            {
                printf("%i",gfx_tilemap_get_tile(t,i,j));
            }
            printf("\n");
        }
        time_sleep(1);
    }while(done!=1);

    //Map mirroring
    int di=0;
    for(int i=t->width-1;i>=(t->width/2)-1;i--)
    {
        for(int j=0;j<=t->height;j++)
        {
            gfx_tilemap_set_tile(t,i,j,gfx_tilemap_get_tile(t,di,j));
        }
        di++;
    }
    gfx_tilemap_set_tile(t,t->width/2,y_door1,1);
    gfx_tilemap_set_tile(t,t->width-1,y_door2,1);
    gfx_tilemap_set_tile(t,t->width-1,y_door1,5);
    gfx_tilemap_set_tile(t,t->width/2,y_door2,4);
}

GFX_Tilemap* gfx_tilemap_read(const char *filename)
{
    char fileName[256];
    sprintf(fileName, "%s.txt", filename);
    FILE *fp = fopen(fileName, "r");
    int width, height, tilesInChar;
    if(fp == 0) { return 0; }

    fscanf(fp, "%d\n%d\n%s\n", &width, &height, fileName);
    GFX_Tilemap *t = gfx_tilemap_create(fileName, width, height);

    for(int i=0;i<width*height;i++)
    {
        tilesInChar = fgetc(fp);
        t->tiles[i]=tilesInChar-'0';
    }
    fclose(fp);
    return t;
}
